<?php

/**
 * 
 * Plugin to check if the user has access to the module/controller/action requested
 * 
 * @author Martin Bianculli
 * @todo Read the public locations from the configuration file
 * @todo Read the redirect location from the configuration file
 *
 */
class Acl_Plugin extends Zend_Controller_Plugin_Abstract {

    private $_public = array(
    	'default/login',    	
    	'default/error', 
    	'default/index'
    );
    
    private $_redirect = array(
    	'module' => 'default', 
    	'controller' => 'login', 
    	'action' => 'index'
    );

    private $_action;

    private $_role;

    /**
     * preDispatch
     * 
     * @param Zend_Controller_Request_Abstract $request
     */
    public function preDispatch(Zend_Controller_Request_Abstract $request) {
        $this->_action = $this->getRequest()->getActionName();
        $this->_resources = array(
        	'*', 
            $this->getRequest()->getModuleName(), 
            $this->getRequest()->getModuleName().'/'.$this->getRequest()->getControllerName(),
            $this->getRequest()->getModuleName().'/'.$this->getRequest()->getControllerName().'/'.$this->getRequest()->getActionName()             
        );                
        
        if (!$this->_isPublic()) {                                       
            if (!$this->_isUserLogged(Zend_Auth::getInstance()) || 
                !$this->_isAllowed(Model_User::getLoggedUser()->getRoleName(), Zend_Registry::get('acl'))) 
            {            
                $request->setModuleName($this->_redirect['module']);
                $request->setControllerName($this->_redirect['controller']);
                $request->setActionName($this->_redirect['action']);
            }            
        }
    }
    
    /**     
     * Check if the user wants to access a public location
     * 
     * @return boolean
     */
    private function _isPublic() {    
        //print_r($this->_resources);
        foreach ($this->_resources as $res) {            
            if (in_array($res, $this->_public)) return true;
        }
        return false;        
    }

    /**
     * Check user identity using Zend_Auth
     * 
     * @param Zend_Auth $auth
     * @return boolean
     */
    private function _isUserLogged(Zend_Auth $auth) {
        if (!empty($auth) && ($auth instanceof Zend_Auth)) {
            return $auth->hasIdentity();
        }
        return false;
    }

    /**
     * Check permission using Zend_Auth and Zend_Acl
     * 
     * @param String $role_name
     * @param Zend_Auth $auth
     * @return boolean
     */
    private function _isAllowed($role_name, Zend_Acl $acl) {
        if (!($acl instanceof Zend_Acl)) return false;            
                        
        foreach ($this->_resources as $res) {            
            if ($acl->has($res)) {
                if ($acl->isAllowed($role_name, $res, $this->_action) || 
                    $acl->isAllowed($role_name, $res, '*')) return true;                
            }
        }
        return false;
    }
}
